Arrow keys / Space to navigate

Module 10: Serverless Application Security

Developing Serverless Solutions on AWS

Topics

Shared Responsibility for Serverless

Analogy: Apartment building. AWS manages the building structure, elevators, plumbing (infrastructure). You lock your own door, choose who gets a key, and protect your belongings (code, data, access).
AWS Manages (OF the cloud)You Manage (IN the cloud)
Physical infrastructure, hardwareFunction code and dependencies
Execution environment, OS patchingIAM roles and permissions (least privilege)
Network isolation between tenantsData encryption configuration
Service availability and durabilityApplication-level access control
API Gateway TLS terminationAPI authorization (JWT, Lambda auth)
DynamoDB storage encryptionFine-grained access, item-level

Key difference from EC2: No OS to patch, no network to configure. But you still own IAM, code security, and data protection.

Defense in Depth - Security at All Layers

Analogy: Medieval castle. Moat (CloudFront/WAF) + Walls (API Gateway) + Guards (Lambda IAM) + Vault (encryption). An attacker must breach ALL layers.
Edge CloudFront WAF Shield DDoS + Bot filtering API Gateway Authorizers (JWT/IAM) Rate limiting Request validation Auth + throttle Lambda Execution role (least priv) VPC isolation Code signing Minimal permissions Data Encryption at rest (KMS) TLS in transit Secrets Manager Encrypt everything Audit CloudTrail Config Auto-fix Blocked!

API Gateway Security - Authorizers

AuthorizerHow It WorksBest For
JWT (HTTP API)Validates token signature, expiry, audience, issuerStandard OIDC (Cognito, Okta, Auth0)
Cognito (REST)Validates Cognito user pool tokenApps using Cognito sign-in
Lambda AuthorizerCustom function evaluates token/headers, returns IAM policyCustom auth, legacy tokens, SAML
IAMSigV4 signed requests, checked against IAM policiesService-to-service, internal APIs

Additional Controls

JWT = showing your ID at the door. Lambda authorizer = calling your boss to confirm you work here. IAM = your badge opens the door automatically.

Protecting Your APIs

Request Filtering Pipeline Requests (good + bad) WAF SQL injection, XSS Bot control, geo-block Rate Limit Token bucket algo Per stage/route/client Validation JSON schema check Required params Authorizer JWT / Lambda / IAM Lambda Bad requests blocked at each layer

Lambda Security - Permissions

Analogy: Office building. Execution role = your badge (what rooms YOU can enter). Resource policy = the visitor list (who can CALL you). Both are needed.
Policy TypeControlsExample
Execution RoleWhat the function CAN do (outbound)Allow dynamodb:GetItem on orders-table
Resource PolicyWho can INVOKE the function (inbound)Allow API Gateway to invoke

Least Privilege Per Function

# BAD: One role with broad access for all functions
"Action": "dynamodb:*", "Resource": "*"

# GOOD: Separate role per function with minimal access
# GET function:
"Action": ["dynamodb:GetItem"], "Resource": "arn:...:table/orders"
# PUT function:
"Action": ["dynamodb:PutItem"], "Resource": "arn:...:table/orders"

Lambda and VPCs

Accessing Lambda FROM your VPC

VPC = private office network. Lambda runs in a public hallway by default. Connecting it to VPC = giving it a keycard to enter the private office. VPC endpoints = internal mail room (no need to go outside).

Protecting Against Attacks

SQL Injection - Use Prepared Statements

# BAD - vulnerable to injection
query = f"SELECT * FROM employees WHERE name = '{user_input}'"

# GOOD - parameterized query (safe)
cursor.execute("SELECT * FROM employees WHERE name = %s", (user_input,))

Other Protections

SQL injection = someone writing on your order form to trick the kitchen into giving away all the food. Prepared statements = a form with fixed boxes that can only hold the expected data type.

Data Protection

ServiceAt RestIn Transit
DynamoDBKMS encryption (default: AWS owned key, option: CMK)TLS (all connections)
S3SSE-S3 (default), SSE-KMS, or SSE-CTLS + enforce via bucket policy
Lambda env varsEncrypted with KMS (default or custom key)TLS for all AWS API calls
API GatewayCache encryption (optional)HTTPS only (TLS 1.2+)

S3 + CloudFront Protection

Auditing, Traceability & Automation

ServiceWhat It Does
CloudTrailRecords ALL API calls (who did what, when, from where)
AWS ConfigTracks resource configuration changes over time + compliance rules
EventBridgeReact to security events in real-time (trigger auto-remediation)
GuardDutyThreat detection using ML (anomalous API calls, compromised credentials)

Security Automation Example

# Auto-remediation: If S3 bucket made public -> revert immediately
EventBridge Rule: source=aws.config, detail-type=Config Rules Compliance Change
  -> filter: NON_COMPLIANT + s3-bucket-public-read
  -> target: Lambda function that sets bucket ACL back to private
CloudTrail = security cameras. Config = building inspector (checks code compliance). EventBridge+Lambda = automatic alarm + lock that triggers when someone opens a window.

What's New (2024-2025)

Q1: In the shared responsibility model for Lambda, what does AWS manage?

B) OS patching and runtime security
AWS manages the execution environment, OS, and runtime. You manage your code, permissions, and configuration.
A: You define IAM roles. C: Your code, your responsibility. D: You configure authorizers.

Q2: Which API Gateway feature prevents SQL injection attacks reaching your backend?

B) AWS WAF with SQL injection rules
WAF inspects request bodies and parameters for SQL injection patterns and blocks them before reaching your code.
A: Rate limiting prevents volume attacks, not content-based. C: JWT validates identity, not payload content. D: Caching improves performance, not security filtering.

Q3: What's the difference between Lambda execution role and resource policy?

B) Execution role = outbound permissions; Resource policy = inbound invocation
Execution role defines what AWS resources the function can access (DynamoDB, S3). Resource policy defines which principals can invoke the function (API Gateway, S3 events).
A: Only resource policy controls invocation. C: VPC is separate config. D: Execution role applies to all invocations.

Q4: How should you store database credentials for a Lambda function?

C) AWS Secrets Manager with automatic rotation
Secrets Manager encrypts credentials, provides IAM-controlled access, supports automatic rotation, and integrates with RDS Proxy.
A: Hardcoding = anyone with code access sees credentials. B: Env vars are better than hardcoding but don't support rotation. D: Never store secrets publicly.

Live Demo: WAF + API Gateway Protection

Demonstrate how WAF blocks SQL injection attacks before they reach your Lambda function.

Attacker WAF API Gateway Lambda DynamoDB SQL injection BLOCKED here! X

Demo Step 1: Create WAF Web ACL

# Create Web ACL with SQL injection protection
aws wafv2 create-web-acl \
  --name serverless-demo-waf \
  --scope REGIONAL \
  --default-action Allow={} \
  --rules '[{
    "Name": "SQLInjectionRule",
    "Priority": 1,
    "Statement": {
      "ManagedRuleGroupStatement": {
        "VendorName": "AWS",
        "Name": "AWSManagedRulesSQLiRuleSet"
      }
    },
    "Action": {"Block": {}},
    "VisibilityConfig": {
      "SampledRequestsEnabled": true,
      "CloudWatchMetricsEnabled": true,
      "MetricName": "SQLiRule"
    }
  }]' \
  --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=serverless-demo-waf \
  --region us-west-2

# Note the Web ACL ARN from the output

Demo Step 2: Associate WAF & Test

Associate WAF with API Gateway

# Get your REST API stage ARN
# Format: arn:aws:apigateway:REGION::/restapis/API_ID/stages/STAGE

aws wafv2 associate-web-acl \
  --web-acl-arn arn:aws:wafv2:us-west-2:ACCOUNT:regional/webacl/serverless-demo-waf/ID \
  --resource-arn arn:aws:apigateway:us-west-2::/restapis/API_ID/stages/prod

Test: Normal Request (ALLOWED)

curl "https://API_ID.execute-api.us-west-2.amazonaws.com/prod/items?name=laptop"
# 200 OK - normal request passes through

Test: SQL Injection Attempt (BLOCKED)

curl "https://API_ID.execute-api.us-west-2.amazonaws.com/prod/items?name=1' OR '1'='1"
# 403 Forbidden - WAF blocks the request!

curl -X POST "https://API_ID.execute-api.us-west-2.amazonaws.com/prod/items" \
  -d '{"name": "'; DROP TABLE users; --"}'
# 403 Forbidden - SQL injection in body also blocked!

Demo: What to Show in Console

ServiceWhat to Demonstrate
WAF ConsoleShow Web ACL rules, sampled requests (blocked vs allowed), metrics graph
API GatewayShow authorizer config, resource policy, throttling settings
LambdaShow execution role (minimal permissions), VPC config if attached
CloudTrailShow API call history (who invoked what)
ConfigShow compliance rules (lambda-function-public-access-prohibited)

Cleanup

aws wafv2 disassociate-web-acl --resource-arn arn:aws:apigateway:...
aws wafv2 delete-web-acl --name serverless-demo-waf --scope REGIONAL --id ID --lock-token TOKEN

Module Summary